import 'package:flutter/foundation.dart';
import 'package:rongcloud_im_wrapper_plugin/rongcloud_im_wrapper_plugin.dart';
import 'package:shared_preferences/shared_preferences.dart';

import '../pages/message/utils/bt_constants.dart';
import '../pages/utils/bt_constants.dart';
import '../pages/utils/bt_event_bus.dart';

class BtRcImEngine {
  RCIMIWEngine? _engine;

  BtRcImEngine._internal();

  factory BtRcImEngine() => _instance;

  static final BtRcImEngine _instance = BtRcImEngine._internal();

  RCIMIWEngine? get engine => _engine;

  final List<RCIMIWMessage> _receivedMessageList = [];

  List<RCIMIWMessage> get receivedMessageList => _receivedMessageList;

  Future<void> initRcImEngine(String token) async {
    final SharedPreferences prefs = await SharedPreferences.getInstance();
    String appKey = prefs.getString(rongCloudKey) ?? '';
    if (appKey.isEmpty) {
      return;
    }

    RCIMIWEngineOptions options = RCIMIWEngineOptions.create();
    _engine = await RCIMIWEngine.create(appKey, options);
    _connect(token);
  }

  Future<void> _connect(String token) async {
    _engine?.onConnectionStatusChanged = (RCIMIWConnectionStatus? status) {
      if (kDebugMode) {
        print('im onConnectionStatusChanged: ${status.toString()}');
      }
    };
    RCIMIWConnectCallback? callback = RCIMIWConnectCallback(
      onDatabaseOpened: (int? code) {},
      onConnected: (int? code, String? userId) {
        if (kDebugMode) {
          print('-RC-IM-connect---$code---$userId');
        }
        if (code == 0) {
          _setMessageReceivedListener();
        }
      },
    );

    await _engine?.connect(token, 10, callback: callback);
  }

  void _setMessageReceivedListener() {
    _engine?.onMessageReceived = (
      RCIMIWMessage? message,
      int? left,
      bool? offline,
      bool? hasPackage,
    ) {
      if (message != null) {
        _receivedMessageList.add(message);
        eventBus.fire(BtEventFn(messageReceived, obj: message));
      }
    };
  }

  void pullHistoryMessages(String targetId, int mostOldMessageTime, {IRCIMIWGetMessagesCallback? callback}) {
    _engine?.getMessages(
      RCIMIWConversationType.private,
      targetId,
      null,
      mostOldMessageTime,
      RCIMIWTimeOrder.before,
      RCIMIWMessageOperationPolicy.local,
      20,
      callback: callback,
    );
  }

  Future<RCIMIWTextMessage?> createTextMessage(String targetId, String messageText) async {
    RCIMIWTextMessage? textMessage =
        await _engine?.createTextMessage(RCIMIWConversationType.private, targetId, null, messageText);

    return textMessage;
  }

  Future<void> sendTextMessage(RCIMIWTextMessage? textMessage, {RCIMIWSendMessageCallback? callback}) async {
    await _engine?.sendMessage(textMessage as RCIMIWMessage, callback: callback);
  }

  Future<RCIMIWVoiceMessage?> createVoiceMessage(String targetId, String path, int duration) async {
    RCIMIWVoiceMessage? voiceMessage =
        await _engine?.createVoiceMessage(RCIMIWConversationType.private, targetId, null, path, duration);

    return voiceMessage;
  }

  Future<void> sendVoiceMessage(
      RCIMIWVoiceMessage? voiceMessage, RCIMIWSendMediaMessageListener? listener) async {
    await _engine?.sendMediaMessage(voiceMessage as RCIMIWMediaMessage, listener: listener);
  }

  Future<RCIMIWImageMessage?> createImageMessage(String targetId, String path) async {
    RCIMIWImageMessage? message =
        await engine?.createImageMessage(RCIMIWConversationType.private, targetId, null, path);

    return message;
  }

  Future<void> sendImageMessage(RCIMIWImageMessage? message, RCIMIWSendMediaMessageListener? listener) async {
    await _engine?.sendMediaMessage(message as RCIMIWMediaMessage, listener: listener);
  }

  Future<RCIMIWFileMessage?> createFileMessage(String targetId, String path) async {
    RCIMIWFileMessage? message =
        await engine?.createFileMessage(RCIMIWConversationType.private, targetId, null, path);

    return message;
  }

  Future<void> sendFileMessage(RCIMIWFileMessage? message, RCIMIWSendMediaMessageListener? listener) async {
    await _engine?.sendMediaMessage(message as RCIMIWMediaMessage, listener: listener);
  }

  Future<int?> clearUnreadCount(String targetId, int lastMessageTimestamp) async {
    int? code =
        await _engine?.clearUnreadCount(RCIMIWConversationType.private, targetId, null, lastMessageTimestamp);
    return code;
  }

  Future<void> removeConversation(String targetId) async {
    await _engine?.removeConversation(RCIMIWConversationType.private, targetId, null);
    eventBus.fire(BtEventFn(freshConversationList));
  }

  Future<void> destroy() async {
    await _engine?.disconnect(false);
    await _engine?.destroy();
  }
}
